import csv
import os
import subprocess
import tempfile
import time
from typing import Dict, Any, List

from config import settings


class CppExecutor:
    """
    C++程序执行器，用于调用现有的稳定匹配算法
    """

    def __init__(self, cpp_executable_path: str = None):
        # 使用配置中的路径
        self.cpp_executable_path = cpp_executable_path or settings.CPP_EXECUTABLE_PATH

        # 使用配置中的数据文件路径
        self.default_data_paths = {
            "network": settings.NETWORK_DATA_FILE,
            "shipment": settings.SHIPMENT_DATA_FILE,
            "route": settings.ROUTE_DATA_FILE,
            "cooperation": settings.COOPERATION_DATA_FILE
        }

    def check_executable_exists(self) -> bool:
        """
        检查C++可执行文件是否存在
        """
        return os.path.exists(self.cpp_executable_path)

    def run_matching_algorithm(self,
                               network_file: str = None,
                               shipment_file: str = None,
                               route_file: str = None,
                               cooperation_file: str = None) -> Dict[str, Any]:
        """
        运行匹配算法
        
        Args:
            network_file: 网络数据文件路径
            shipment_file: 货物数据文件路径
            route_file: 路线数据文件路径
            cooperation_file: 合作参数文件路径
            
        Returns:
            算法执行结果
        """
        # 使用默认路径如果未提供
        network_file = network_file or self.default_data_paths["network"]
        shipment_file = shipment_file or self.default_data_paths["shipment"]
        route_file = route_file or self.default_data_paths["route"]
        cooperation_file = cooperation_file or self.default_data_paths["cooperation"]

        # 检查文件是否存在
        missing_files = []
        for file_path, file_name in [(network_file, "network"),
                                     (shipment_file, "shipment"),
                                     (route_file, "route"),
                                     (cooperation_file, "cooperation")]:
            if not os.path.exists(file_path):
                missing_files.append(file_name)

        if missing_files:
            raise FileNotFoundError(f"Missing data files: {', '.join(missing_files)}")

        # 创建临时结果文件
        with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as tmp_result:
            result_file_path = tmp_result.name

        try:
            # 构建命令行参数
            # 注意：需要根据实际的C++程序接口调整参数格式
            cmd = [
                self.cpp_executable_path,
                network_file,
                shipment_file,
                route_file,
                cooperation_file,
                result_file_path
            ]

            # 记录开始时间
            start_time = time.time()
            
            # 执行C++程序
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=300  # 5分钟超时
            )

            # 记录结束时间
            end_time = time.time()
            execution_time = end_time - start_time

            # 检查执行结果
            if result.returncode != 0:
                raise RuntimeError(f"C++ program execution failed with return code {result.returncode}: {result.stderr}")

            # 解析结果文件
            matching_results = self._parse_result_file(result_file_path)

            # 添加执行信息
            matching_results["execution_info"] = {
                "stdout": result.stdout,
                "stderr": result.stderr,
                "return_code": result.returncode,
                "execution_time": execution_time
            }

            return matching_results

        finally:
            # 清理临时文件
            if os.path.exists(result_file_path):
                os.unlink(result_file_path)

    def _parse_result_file(self, result_file_path: str) -> Dict[str, Any]:
        """
        解析结果文件
        
        Args:
            result_file_path: 结果文件路径
            
        Returns:
            解析后的结果数据
        """
        if not os.path.exists(result_file_path):
            raise FileNotFoundError(f"Result file not found: {result_file_path}")

        # 读取CSV结果文件
        with open(result_file_path, 'r') as f:
            reader = csv.reader(f)
            rows = list(reader)

        # 解析数据（根据实际输出格式调整）
        result_data = {
            "shipments_assignment": [],
            "summary": {}
        }

        # 解析实际的输出格式
        if len(rows) >= 8:
            # 解析货物分配
            shipment_ids = rows[0][1:]  # 第一行是shipment ID
            route_assignments = rows[1][1:]  # 第二行是分配的路线
            
            for shipment_id, route in zip(shipment_ids, route_assignments):
                result_data["shipments_assignment"].append({
                    "shipment_id": shipment_id,
                    "assigned_route": route
                })
            
            # 解析摘要信息
            result_data["summary"] = {
                "total_shipments": int(rows[3][1]) if rows[3][1].isdigit() else 0,  # Total container number in shipment
                "matched_shipments": int(rows[4][1]) if rows[4][1].isdigit() else 0,  # Total matched container number
                "stability": rows[5][1].lower() == "true",  # Stable or not
                "iterations": int(rows[6][1]) if rows[6][1].isdigit() else 0,  # Iteration num
                "execution_time": float(rows[7][1]) if self._is_float(rows[7][1]) else 0.0  # CPU time
            }

        return result_data

    def _is_float(self, value: str) -> bool:
        """
        检查字符串是否可以转换为浮点数
        """
        try:
            float(value)
            return True
        except ValueError:
            return False

    def prepare_test_data(self, data_config: Dict[str, Any]) -> Dict[str, str]:
        """
        准备测试数据文件
        
        Args:
            data_config: 数据配置
            
        Returns:
            生成的数据文件路径字典
        """
        data_files = {}

        # 创建临时目录
        temp_dir = tempfile.mkdtemp()

        # 生成网络数据文件
        if "network" in data_config:
            network_file = os.path.join(temp_dir, "network.csv")
            self._generate_network_file(network_file, data_config["network"])
            data_files["network"] = network_file

        # 生成货物数据文件
        if "shipments" in data_config:
            shipment_file = os.path.join(temp_dir, "shipment.csv")
            self._generate_shipment_file(shipment_file, data_config["shipments"])
            data_files["shipment"] = shipment_file

        # 生成路线数据文件
        if "routes" in data_config:
            route_file = os.path.join(temp_dir, "route.csv")
            self._generate_route_file(route_file, data_config["routes"])
            data_files["route"] = route_file

        # 生成合作参数文件
        if "cooperation" in data_config:
            cooperation_file = os.path.join(temp_dir, "cooperation_parameter.csv")
            self._generate_cooperation_file(cooperation_file, data_config["cooperation"])
            data_files["cooperation"] = cooperation_file

        return data_files

    def _generate_network_file(self, file_path: str, data: List[Dict[str, Any]]):
        """生成网络数据文件"""
        with open(file_path, 'w', newline='') as f:
            writer = csv.writer(f)
            # 写入表头和数据
            # 根据实际格式调整
            pass

    def _generate_shipment_file(self, file_path: str, data: List[Dict[str, Any]]):
        """生成货物数据文件"""
        with open(file_path, 'w', newline='') as f:
            writer = csv.writer(f)
            # 写入表头和数据
            # 根据实际格式调整
            pass

    def _generate_route_file(self, file_path: str, data: List[Dict[str, Any]]):
        """生成路线数据文件"""
        with open(file_path, 'w', newline='') as f:
            writer = csv.writer(f)
            # 写入表头和数据
            # 根据实际格式调整
            pass

    def _generate_cooperation_file(self, file_path: str, data: List[Dict[str, Any]]):
        """生成合作参数文件"""
        with open(file_path, 'w', newline='') as f:
            writer = csv.writer(f)
            # 写入表头和数据
            # 根据实际格式调整
            pass